package com.sc.nft.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.meta.component.base.api.CommonResult;
import com.meta.component.base.api.ResultCode;
import com.meta.push.plat.client.api.MetaPushPlatClient;
import com.meta.push.plat.client.enums.PushBusinessTypeEnum;
import com.meta.push.plat.client.enums.PushTypeEnum;
import com.meta.push.plat.client.req.PushMessageBodyRequest;
import com.meta.push.plat.client.req.PushMessageRequest;
import com.sc.nft.dao.StaticDataDao;
import com.sc.nft.dao.UserPushConfDao;
import com.sc.nft.dao.UserRelationPushCidDao;
import com.sc.nft.dto.MallOrderPushDTO;
import com.sc.nft.dto.MallOrderPushResultDTO;
import com.sc.nft.dto.PushMessageExtendDTO;
import com.sc.nft.entity.*;
import com.sc.nft.enums.MallOrderPushTypeEnum;
import com.sc.nft.enums.PushMessageExtendBusinessEnum;
import com.sc.nft.enums.PushSourceEnum;
import com.sc.nft.service.MallOrderProductService;
import com.sc.nft.service.MallOrderPushService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 刘国航
 * @desc
 * @since 2024/6/12 21:51
 */
@Slf4j
@Service
public class MallOrderPushServiceImpl implements MallOrderPushService {

    @Autowired
    private MallOrderProductService mallOrderProductService;

    @Autowired
    private MetaPushPlatClient metaPushPlatClient;

    @Autowired
    private UserPushConfDao userPushConfDao;

    @Autowired
    private UserRelationPushCidDao userRelationPushCidDao;

    @Autowired
    private StaticDataDao staticDataDao;

    private final static List<MallOrderPushTypeEnum> approvalList = Arrays.asList(MallOrderPushTypeEnum.ONLY_REFUND_AUTO_APPROVAL,
            MallOrderPushTypeEnum.ONLY_REFUND_DAO_APPROVAL, MallOrderPushTypeEnum.ONLY_REFUND_DAO_REFUND,
            MallOrderPushTypeEnum.ONLY_REFUND_REFUND_SUCCESS, MallOrderPushTypeEnum.REFUNDS_DAO_APPROVAL,
            MallOrderPushTypeEnum.REFUNDS_AUTO_APPROVAL, MallOrderPushTypeEnum.REFUNDS_DAO_REFUND,
            MallOrderPushTypeEnum.REFUNDS_REFUND_SUCCESS, MallOrderPushTypeEnum.EXCHANGE_DAO_APPROVAL,
            MallOrderPushTypeEnum.EXCHANGE_DAO_SHIP, MallOrderPushTypeEnum.EXCHANGE_DAO_REFUND);

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void mallOrderPushMessage(MallOrderPushDTO mallOrderPushDTO, MallOrderPushTypeEnum mallOrderPushTypeEnum) {
        try {
            String pushLimitStartHour = staticDataDao.getByType("push_limit_start_hour").getValue();
            String pushLimitEndHour = staticDataDao.getByType("push_limit_end_hour").getValue();
            //region 默认22点到次日8点不发推送消息
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            int hour = calendar.get(Calendar.HOUR_OF_DAY);
            if (hour >= Integer.parseInt(pushLimitStartHour) || hour < Integer.parseInt(pushLimitEndHour)) {
                return;
            }
            //endregion

            Long userId = null;
            String productName = null;
            Long businessId = null;
            String businessObject = null;

            MallOrderPushResultDTO mallOrderPushResultDTO = null;
            if (MallOrderPushTypeEnum.TO_BE_RECEIPT.getCode().equals(mallOrderPushTypeEnum.getCode())) {
                //当购买的商城订单状态从待发货变为已发货时，向该购买用户推送消息
                mallOrderPushResultDTO = toBeReceipt(mallOrderPushDTO);
            }
            if (MallOrderPushTypeEnum.AUTO_REPLACE_COMPLETE.getCode().equals(mallOrderPushTypeEnum.getCode())) {
                //售后类型为退货换货,系统自动换货已完成
                mallOrderPushResultDTO = autoReplaceComplete(mallOrderPushDTO);
            }
            if (approvalList.contains(mallOrderPushTypeEnum)) {
                mallOrderPushResultDTO = approval(mallOrderPushDTO);
            }
            log.info("mallOrderPushResultDTO=" + JSON.toJSONString(mallOrderPushResultDTO));
            if (Objects.isNull(mallOrderPushResultDTO)) {
                return;
            }

            userId = mallOrderPushResultDTO.getUserId();
            productName = mallOrderPushResultDTO.getProductName();
            businessId = mallOrderPushResultDTO.getBusinessId();
            businessObject = mallOrderPushResultDTO.getBusinessObject();
            if (Objects.isNull(userId)
                    || StrUtil.isBlank(productName)) {
                return;
            }

            UserPushConf userPushConf = userPushConfDao.getByUserId(userId);
            if (Objects.nonNull(userPushConf)) {
                if (!userPushConf.getEnableMallOrderPush()) {
                    return;
                }
            }

            UserRelationPushCid userRelationPushCid = userRelationPushCidDao.getByUserId(userId);
            if (Objects.isNull(userRelationPushCid)) {
                return;
            }
            log.info("userRelationPushCid=" + JSON.toJSONString(userRelationPushCid));
            String finalProductName = productName;
            Long finalBusinessId = businessId;
            String finalBusinessObject = businessObject;
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                @Override
                public void afterCommit() {
                    pushMallMessage(userRelationPushCid.getCid(), mallOrderPushTypeEnum.getTitle(), mallOrderPushTypeEnum.getContent(), finalProductName, finalBusinessId, finalBusinessObject);
                }
            });
        } catch (Exception e) {
            log.error("商城订单推送异常", e);
        }
    }

    /**
     * 推送商城消息
     */
    private void pushMallMessage(String cid, String title, String content, String productName, Long businessId, String businessObject) {
        List<String> cidList = new ArrayList<>();
        cidList.add(cid);
        PushMessageRequest pushMessageRequest = new PushMessageRequest();
        pushMessageRequest.setPushBusinessType(PushBusinessTypeEnum.MALL_PUSH);
        pushMessageRequest.setSource(PushSourceEnum.METAGO.getCode());
        pushMessageRequest.setPushType(PushTypeEnum.SINGLE_PUSH_BY_CID);
        pushMessageRequest.setCid(cidList);
        PushMessageBodyRequest pushMessageBodyRequest = new PushMessageBodyRequest();
        pushMessageBodyRequest.setTitle(title);
        pushMessageBodyRequest.setContent(StrUtil.format(content, productName));
        pushMessageBodyRequest.setUrl("https://www.gometa.com.cn/officalH5");
        pushMessageRequest.setBody(pushMessageBodyRequest);
        PushMessageExtendDTO pushMessageExtendDTO = new PushMessageExtendDTO();
        pushMessageExtendDTO.setBusinessId(businessId);
        pushMessageExtendDTO.setBusinessObject(businessObject);
        pushMessageExtendDTO.setBusinessDesc("商城订单");
        pushMessageRequest.setExtend(JSON.toJSONString(pushMessageExtendDTO));
        log.info("pushMessageRequest=" + JSON.toJSONString(pushMessageRequest));
        CommonResult commonResult = metaPushPlatClient.pushMessage(pushMessageRequest);
        if (!Objects.equals(ResultCode.SUCCESS.getCode(), commonResult.getCode())) {
            log.error(commonResult.getMessage());
        }
    }

    private MallOrderPushResultDTO toBeReceipt(MallOrderPushDTO mallOrderPushDTO) {
        MallOrder mallOrder = mallOrderPushDTO.getMallOrder();
        List<MallOrderProduct> mallOrderProductList = mallOrderProductService.getListByOrderId(mallOrder.getId());
        String productName = mallOrderProductList.stream().map(MallOrderProduct::getProductName).distinct().collect(Collectors.joining(","));
        return new MallOrderPushResultDTO(mallOrder.getUserId(), productName, mallOrder.getId(), PushMessageExtendBusinessEnum.MALL_ORDER.getCode());
    }

    private MallOrderPushResultDTO autoReplaceComplete(MallOrderPushDTO mallOrderPushDTO) {
        MallOrderRefund mallOrderRefund = mallOrderPushDTO.getMallOrderRefund();
        MallOrderProduct mallOrderProduct = mallOrderPushDTO.getMallOrderProduct();
        return new MallOrderPushResultDTO(mallOrderRefund.getUserId(), mallOrderProduct.getProductName(), mallOrderRefund.getId(), PushMessageExtendBusinessEnum.MALL_ORDER_REFUND.getCode());
    }

    private MallOrderPushResultDTO approval(MallOrderPushDTO mallOrderPushDTO) {
        MallOrderRefund mallOrderRefund = mallOrderPushDTO.getMallOrderRefund();
        MallOrderProduct mallOrderProduct = mallOrderProductService.getById(mallOrderRefund.getOrderGoodsId());
        return new MallOrderPushResultDTO(mallOrderRefund.getUserId(), mallOrderProduct.getProductName(), mallOrderRefund.getId(), PushMessageExtendBusinessEnum.MALL_ORDER_REFUND.getCode());
    }

}
